package xyz.ibenben.zhongdian.common.util;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 图片处理类
 *
 * @author hty
 */
@Slf4j
public class ImageUtil {

    /**
     * 给图片指定位置打马赛克
     *
     * @param filePath   图片位置
     * @param targetPath 打码后的图片保存位置，若为空则保存路径默认为原图片路径
     * @param x          图片要打码区域左上角的横坐标
     * @param y          图片要打码区域左上角的纵坐标
     * @param width      图片要打码区域的宽度
     * @param height     图片要打码区域的高度
     * @param mosaicSize 马赛克尺寸，即每个矩形的长宽
     * @return
     * @throws IOException
     */
    @SuppressWarnings("static-access")
    public static boolean mosaic(String filePath, String targetPath,
                                 int x, int y, int width, int height, int mosaicSize) throws IOException {
        if (!isFile(filePath)) {
            return false;
        }
        String suffix = getSuffix(filePath, targetPath);
        if (suffix == null) {
            return false;
        }
        File file = getFile(filePath);
        if (file == null) {
            return false;
        }
        // 读取该图片
        BufferedImage bi = ImageIO.read(file);
        BufferedImage spinImage = new BufferedImage(bi.getWidth(),
                bi.getHeight(), BufferedImage.TYPE_INT_RGB);
        // 马赛克格尺寸太大或太小
        if (bi.getWidth() < mosaicSize || bi.getHeight() < mosaicSize || mosaicSize <= 0) {
            log.error("马赛克尺寸设置不正确");
            return false;
        }

        //2. 设置各方向绘制的马赛克块个数
        // 方向绘制个数
        int xcount;
        // y方向绘制个数
        int ycount;
        if (width % mosaicSize == 0) {
            xcount = width / mosaicSize;
        } else {
            xcount = width / mosaicSize + 1;
        }
        if (height % mosaicSize == 0) {
            ycount = height / mosaicSize;
        } else {
            ycount = height / mosaicSize + 1;
        }

        //3. 绘制马赛克(绘制矩形并填充颜色)
        Graphics gs = spinImage.getGraphics();
        gs.drawImage(bi, 0, 0, null);
        processForRect(xcount, ycount, mosaicSize, width, height, x, y, gs, bi);
        gs.dispose();
        if (targetPath == null || targetPath.isEmpty()) {
            targetPath = filePath;
        }
        File sf = new File(targetPath);
        // 保存图片
        ImageIO.write(spinImage, suffix, sf);
        return true;
    }

    public static boolean mosaicRect(String filePath, String targetPath,
                                     ImageArea area, int mosaicSize) throws IOException {
        return mosaic(filePath, targetPath, area.getX(), area.getY(),
                area.getWidth(), area.getHeight(), mosaicSize);
    }

    /**
     * 给图片多个指定位置打马赛克
     *
     * @param filePath   图片位置
     * @param targetPath 打码后的图片保存位置，若为空则保存路径默认为原图片路径
     * @param areaList   图片区域对象数组
     * @param mosaicSize 马赛克尺寸，即每个矩形的长宽
     * @return
     * @throws IOException
     */
    @SuppressWarnings("static-access")
    public static boolean mosaic(String filePath, String targetPath,
                                 List<ImageArea> areaList, int mosaicSize) throws IOException {
        if (!isFile(filePath)) {
            return false;
        }
        String suffix = getSuffix(filePath, targetPath);
        if (suffix == null) {
            return false;
        }
        File file = getFile(filePath);
        if (file == null) {
            return false;
        }
        // 读取该图片
        BufferedImage bi = ImageIO.read(file);
        BufferedImage spinImage = new BufferedImage(bi.getWidth(),
                bi.getHeight(), BufferedImage.TYPE_INT_RGB);
        // 马赛克格尺寸太大或太小
        if (bi.getWidth() < mosaicSize || bi.getHeight() < mosaicSize || mosaicSize <= 0) {
            log.error("马赛克尺寸设置不正确");
            return false;
        }

        Graphics gs = spinImage.getGraphics();
        gs.drawImage(bi, 0, 0, null);
        //对每一个局部区域分别绘制马赛克
        for (ImageArea imageArea : areaList) {
            int x = imageArea.getX();
            int y = imageArea.getY();
            int width = imageArea.getWidth();
            int height = imageArea.getHeight();
            //2. 设置各方向绘制的马赛克块个数
            // 方向绘制个数
            int xcount;
            // y方向绘制个数
            int ycount;
            if (width % mosaicSize == 0) {
                xcount = width / mosaicSize;
            } else {
                xcount = width / mosaicSize + 1;
            }
            if (height % mosaicSize == 0) {
                ycount = height / mosaicSize;
            } else {
                ycount = height / mosaicSize + 1;
            }

            //3. 绘制马赛克(绘制矩形并填充颜色)
            processForRect(xcount, ycount, mosaicSize, width, height, x, y, gs, bi);

        }
        gs.dispose();
        if (targetPath == null || targetPath.isEmpty()) {
            targetPath = filePath;
        }
        File sf = new File(targetPath);
        // 保存图片
        ImageIO.write(spinImage, suffix, sf);
        return true;
    }

    private static void processForRect(int xcount, int ycount, int mosaicSize, int width, int height, int x,
                                       int y, Graphics gs, BufferedImage bi) {
        int xTmp = x;
        int yTmp = y;
        for (int i = 0; i < xcount; i++) {
            for (int j = 0; j < ycount; j++) {
                //马赛克矩形格大小
                int mwidth = mosaicSize;
                int mheight = mosaicSize;
                if (i == xcount - 1) {
                    //横向最后一个比较特殊，可能不够一个size
                    mwidth = width - xTmp;
                }
                if (j == ycount - 1) {
                    //同理
                    mheight = height - yTmp;
                }
                //矩形颜色取中心像素点RGB值
                int centerX = xTmp;
                int centerY = yTmp;
                if (mwidth % 2 == 0) {
                    centerX += mwidth / 2;
                } else {
                    centerX += (mwidth - 1) / 2;
                }
                if (mheight % 2 == 0) {
                    centerY += mheight / 2;
                } else {
                    centerY += (mheight - 1) / 2;
                }
                Color color = new Color(bi.getRGB(centerX, centerY));
                gs.setColor(color);
                gs.fillRect(xTmp, yTmp, mwidth, mheight);
                // 计算下一个矩形的y坐标
                yTmp = yTmp + mosaicSize;
            }
            // 还原y坐标
            yTmp = y;
            // 计算x坐标
            xTmp = xTmp + mosaicSize;
        }
    }

    private static boolean isFile(String filePath) {
        //1. 初始化图像处理各变量
        if (!filePath.endsWith(".png") && !filePath.endsWith(".jpg") &&
                !filePath.endsWith(".gif")) {
            log.error("ImageUtil>>>文件名非法，不是正确的图片文件名");
            return false;
        }
        return true;
    }

    private static String getSuffix(String filePath, String targetPath) {
        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
        if (targetPath != null && !targetPath.isEmpty() && !targetPath.endsWith(suffix)) {
            log.error("ImageUtil>>>目标文件后缀应与源文件后缀一致");
            return null;
        }
        return suffix;
    }

    private static File getFile(String filePath) {
        File file = new File(filePath);
        if (!file.isFile()) {
            log.error("ImageUtil>>>" + filePath + "不是一个文件！");
            return null;
        }
        return file;
    }

    public static void main(String[] args) {
        try {
            ImageUtil.mosaicRect("C:\\Users\\admin\\Desktop\\image\\0a3f63fb1c5edbdccfe0dbc45895d56d.jpg",
                    "C:\\Users\\admin\\Desktop\\image\\0.jpg", new ImageArea(400, 250, 500, 300), 40);
        } catch (IOException e) {
            log.error("出错了！！！！", e);
        }
    }

}
